#include <stdio.h>

int main(void){
	char board[3][3] = {
						{'1','2','3'},
						{'4','5','6'},
						{'7','8','9'}

						};

	printf("address of board      : %p \n",board);
	printf("address of board[0][0]: %p \n", &board[0][0]);
	printf("value of board[0]: %p \n",board[0]);
	/***
	board, board[0]和board[0][0]的数值相同，但它们并不是相同的东西：
	board是char型二维数组的地址，
	board[0]是char型一维子数组的地址，它是board的一个子数组，
	&board[0][0]是char型数组元素的地址。
	*/


	printf("value of board[0][0] : %c\n", board[0][0]);
	printf("value of *board[0] : %c\n", *board[0]);
	printf("value of **board : %c\n", **board);
	/*
	可以看到，如果使用board获取第一个元素的值，就需要使用两个间接运算符**board
	如果只使用一个*，只会得到子数组的第一个元素，即board[0]引用的地址。

	*/


	for(int i=0;i<9;++i){
		printf("board: %c\n", *(*board+i));
	}
	printf("========================\n");
	/**
	可以看到，使用表达式*(*board+i)可以得到一个数组元素的值。括号中的表达式*board+i会得到board数组中偏移量为i的元素地址
	只使用board，就是在使用char**类型的地址值。取消对board的引用，会得到相同的地址值，但其类型是char*。给它加i会得到一个char*的地址，它是内存中的第i个元素，即数组中的一个字符。取消对它的引用，会得到该地址中存储的内容。  
	括号在这里很重要的。省略它们会得到board所指向的值（即存储在board中的地址所引用的值）再加上i的值。因此，如果i的值是2，*board+i会得到数组的第一个元素值加2,。我们真正想要的是将i的值加到board中的地址，然后对这个新地址取消引用，得到一个值。
	*/


	for(int i=0;i<9;++i){
		printf("board: %c\n", **board+i);
	}
	printf("========================\n");
	/**
	这是值虽然和上面的*(*board+i)一样，但只是因为i的值加到的数组board中的第一个元素（这个元素用表达式**board来访问）上，刚好就是ASCII表中的字符从'1'到'9'  
	*/



	char *pboard = *board;  //A pointer to char
	for(int i=0;i<9;i++)
		printf("board: %c\n", *(pboard+i));
	printf("========================\n");


	


	return 0;
}/**Output：
address of board      : 0x7ffdead7931f 
address of board[0][0]: 0x7ffdead7931f 
value of board[0]: 0x7ffdead7931f 
value of board[0][0] : 1
value of *board[0] : 1
value of **board : 1
board: 1
board: 2
board: 3
board: 4
board: 5
board: 6
board: 7
board: 8
board: 9
========================
board: 1
board: 2
board: 3
board: 4
board: 5
board: 6
board: 7
board: 8
board: 9
========================
board: 1
board: 2
board: 3
board: 4
board: 5
board: 6
board: 7
board: 8
board: 9
========================


*/